package com.zenika.zenbinding.rebind;

import java.io.PrintWriter;
import java.util.Iterator;
import java.util.List;

import com.google.gwt.core.ext.GeneratorContext;
import com.google.gwt.core.ext.TreeLogger;
import com.google.gwt.core.ext.typeinfo.JClassType;
import com.google.gwt.core.ext.typeinfo.NotFoundException;
import com.google.gwt.core.ext.typeinfo.TypeOracle;
import com.google.gwt.user.rebind.ClassSourceFileComposerFactory;
import com.google.gwt.user.rebind.SourceWriter;

public class WrapperLoaderCreator {

	private TreeLogger logger;
	private GeneratorContext context;
	private TypeOracle typeOracle;
	private String typename;

	public WrapperLoaderCreator(TreeLogger logger, GeneratorContext context, String requestedClass) {
		this.logger = logger;
		this.context = context;
		this.typeOracle = context.getTypeOracle();
		this.typename = requestedClass;
	}

	public String createLinker() {
		SourceWriter source = null;
		try {
			source = this.getSourceWriter(this.typeOracle.getType(this.typename));
		} catch (NotFoundException e) {
			e.printStackTrace();
		}
		if (source == null) {
			return this.typename + "Impl";
		} else {
			this.createGetWrapperMethod(source);
			// this.createCloneMethod(source);
			return this.typename + "Impl";
		}
	}

	private void createGetWrapperMethod(SourceWriter source) {
		source.println("public Wrapper get(String className) {");
		source.indent();
		List<String> bindableList = BindingParser.getBindableList();
		Iterator<String> iter = bindableList.iterator();
		while (iter.hasNext()) {
			String className = (String) iter.next();
			// String[] decomp = className.split("\\.");
			// String classSimpleName = decomp[decomp.length - 1];
			source.println("if (className.equals(\"" + className + "\")) {");
			source.indent();
			source.println("return (Wrapper) GWT.create(" + className + ".class);");
			source.outdent();
			source.println("}");
		}
		source.println("return null;");
		source.outdent();
		source.println("}");
		// source.outdent();
		// source.println("}");
		source.commit(this.logger);
	}

	/**
	 * SourceWriter instantiation. Return null if the resource already exist.
	 * @return sourceWriter
	 */
	public SourceWriter getSourceWriter(JClassType classType) {
		String packageName = classType.getPackage().getName();
		String simpleName = classType.getSimpleSourceName() + "Impl";
		ClassSourceFileComposerFactory composer = new ClassSourceFileComposerFactory(packageName, simpleName);
		composer.setSuperclass(classType.getName());
		composer.addImport("com.zenika.zenbinding.client.util.Wrapper");
		composer.addImport("com.google.gwt.core.client.GWT");
		PrintWriter printWriter = this.context.tryCreate(this.logger, packageName, simpleName);
		if (printWriter == null) {
			return null;
		} else {
			SourceWriter sw = composer.createSourceWriter(this.context, printWriter);
			return sw;
		}
	}

}
